#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <string>
#include <stdlib.h>
#include <sys/wait.h>

// // 保存信号

// void PrintPending(const sigset_t &pending)
// {
// 	std::cout << "curr pending list[" << getpid() << "]" << std::endl;
// 	for(int signo = 31;signo > 0;signo--)
// 	{
// 		if(sigismember(&pending,signo))
// 			std::cout << 1;
// 		else
// 			std::cout << 0;
// 	}
// 	std::cout << std::endl;
// }
// int main()
// {
// 	::signal(2,SIG_IGN);//忽略2号进程，即使后续解除屏蔽，该信号也不会终止进程

// 	// 1. 对2号信号进行屏蔽
// 	// 1.1 在栈上开辟空间，创建信号集，block新屏蔽集，oblock旧，用于恢复
// 	sigset_t block,oblock;
// 	sigemptyset(&block);  //初始化信号集
// 	sigemptyset(&oblock);

// 	// 1.2 添加2号信号
// 	//我们并没有设置进入内核中，只是在用户栈上设置了一个block位图结构
// 	sigaddset(&block,2); //将2号信号添加到屏蔽集

// 	// 1.3 设置进入内核
// 	// 将当前进程的信号屏蔽字设置为block,保存旧屏蔽字到oblock
// 	sigprocmask(SIG_SETMASK,&block,&oblock);

// 	int cnt = 0;

// 	while(1)
// 	{
// 		//2. 如何获取pending表？
// 		sigset_t pending;
// 		sigpending(&pending); // 获取当前未决信号集

// 		//2.1 打印
// 		PrintPending(pending);

// 		sleep(1);

// 		cnt++;
// 		if(cnt == 10)
// 		{
// 			std::cout << "解除对2号信号的屏蔽" << std::endl;
// 			sigprocmask(SIG_SETMASK,&oblock,nullptr); // 恢复旧屏蔽集
// 		}
// 	}

// 	return 0;
// }




// 捕捉信号


// // OS不允许信号处理方法进行嵌套 -- 当某一个信号正在被处理
// // -- OS会自动把对应信号的block位置为1 -- 信号处理返回内核时，自动置为0

// // 证明block被置为1 打印一下block位图
// void PrintBlock()
// {
// 	sigset_t set,oset;
// 	sigemptyset(&set);
// 	sigemptyset(&oset);

// 	sigprocmask(SIG_BLOCK,&set,&oset);

// 	std::cout << "block";
// 	for(int signo = 31;signo > 0;signo--)
// 	{
// 		if(sigismember(&oset,signo))
// 			std::cout << 1;
// 		else
// 			std::cout << 0;
// 	}
// 	std::cout << std::endl;
// }

// // 证明pending位图
// void PrintPending()
// {
// 	sigset_t pending;
// 	::sigpending(&pending);

// 	std::cout << "pending: ";
// 	for(int signo = 31;signo > 0;signo--)
// 	{
// 		if(sigismember(&pending,signo))
// 			std::cout << 1;
// 		else
// 			std::cout << 0;
// 	}
// 	std::cout << std::endl;
// }

// void handler(int signo)
// {
// 	static int cnt = 0;
// 	cnt++;
// 	while (1)
// 	{
// 		std::cout << getpid() << "  get a sig: " << signo << ",cnt: " << cnt << std::endl;	
// 		PrintPending(); 
// 		sleep(1);
// 		//break;
// 	}
// 	//exit(1);
// }

// int main()
// {
// 	struct sigaction act, oact;
// 	act.sa_handler = handler;

// 	sigemptyset(&act.sa_mask);

// 	sigaddset(&act.sa_mask,3); // 信号处理期间要阻塞的信号集
// 	sigaddset(&act.sa_mask,4); // 信号屏蔽
// 	sigaddset(&act.sa_mask,5);
// 	sigaddset(&act.sa_mask,6);
// 	sigaddset(&act.sa_mask,7);

// 	::sigaction(2, &act, &oact);


// 	while (1)
// 	{
// 		// PrintBlock();

// 		// 打印全为0，证明在处理信号(handler)之前由1->0
// 		// 当进程解除对该信号的阻塞时，内核检查 pending 位图，若对应位为 1，
// 		// 则将信号交付给进程处理（调用信号处理函数），并将该位清 0。
// 		PrintPending(); 
// 		pause();
// 	}

// 	return 0;
// }







// volatile 易变关键字
// 优化到寄存器里没有意义

// 保持内存可见性
volatile int flag = 0;

void change(int signo) // 信号捕捉的执行流
{
	(void) signo;

	flag = 1;
	printf("change flag 0->1,getpid:%d\n",getpid());
}

//  寄存器+优化：屏蔽了内存的可见性，编译器优化会优化错
//  优化后的代码，不会退出进程
//  因为优化的代码，数据在寄存器上，每次从寄存器读取，而不从内存读取
int main()
{
	printf("main process,pid:%d\n",getpid());
	signal(2,change);

	while(!flag); // 主执行流---flag没有任何修改
	printf("我正常退出\n");

}